package com.alogic.xscript.cert;

import com.alogic.xscript.ExecuteWatcher;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.alogic.xscript.plugins.Segment;
import com.anysoft.util.IOTools;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;


/**
 * 从Pem证书中加载证书对象
 */
public class CertPem extends Segment {
    protected String id;
    protected String cid = "$certificate";
    protected String $content = "";

    public CertPem(String tag, Logiclet p) {
        super(tag, p);

        registerModule("cert-query-all",CertQueryAll.class);
    }

    @Override
    public void configure(Properties p){
        super.configure(p);
        id = PropertiesConstants.getString(p, "id", "$" + this.getXmlTag(),true);
        cid = PropertiesConstants.getString(p, "cid", cid,true);
        $content = PropertiesConstants.getRaw(p,"content","");
    }

    @Override
    protected void onExecute(XsObject root, XsObject current, LogicletContext ctx, ExecuteWatcher watcher) {
        String content = PropertiesConstants.transform(ctx,$content,"");
        boolean result = true;
        String reason = "ok";
        if (StringUtils.isNotEmpty(content)){
            PemReader reader= new PemReader(new StringReader(content));
            try {
                PemObject pemObject = reader.readPemObject();
                if (pemObject != null){
                    CertificateFactory cf = CertificateFactory.getInstance("X.509");
                    X509Certificate certificate = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(pemObject.getContent()));
                    if (StringUtils.isNotEmpty(cid)){
                        ctx.setObject(cid,certificate);
                        try {
                            super.onExecute(root, current, ctx, watcher);
                        }finally {
                            ctx.removeObject(cid);
                        }
                    }
                }
            } catch (IOException e) {
                result = false;
                reason = e.getMessage();
            } catch (CertificateException e) {
                result = false;
                reason = e.getMessage();
            } finally {
                IOTools.close(reader);
            }
        }
        ctx.SetValue(id, BooleanUtils.toStringTrueFalse(result));
        ctx.SetValue(String.format("%s.reason",id),reason);
    }
}
